/* 
 * File:   main.cpp
 * Author: minaev
 *
 * Created on 5 Сентябрь 2013 г., 10:27
 */

#include <cstdlib>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <fcntl.h>
#include <iostream>

//POSIX Thread
#include <pthread.h>

//Berkeley sockets
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <queue>
#include <iostream>


#include "main.h"
#include "Xservice.h"
#include "Xmsg.h"
#include "Xcom.h"
#include "XUDPServ.h"
#include "XbeeIf.h"
#include "XTimeOut.h"
#include "Xpack.h"
#include "XshareLine.h"
#include "XshareMem.h"
#include "XUDPScaner.h"
#include "XUDPShareMem.h"
#include "XpackHandler.h"
#include "XbeeContainer.h"
#include "Xpinger.h"
#include "oustream.h"
#include "ADCXpackDetector.h"
#include "ButtonXpackDetector.h"
#include "PingXpackDetector.h"


using namespace std;

int main(int argc, char** argv, char** env) {
    
    char* ttyDevice = Xservice::copyStr("/dev/ttyUSB0");
    in_addr_t logAddress = 0xffffffff;
    in_addr_t broadcastAddress = 0xff00a8c0;


    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            switch (argv[i][1]) {
                case 'h':{
                    printf("XbeeServer for magenta medical dropper\n"
                            "xbee_serv_c [OPTIONS]\n"
                            "   -d <path_to_dev> - tty for xbee coordinator\n"
                            "   -b <xxx.xxx.xxx.xxx> - broadcast ip\n"
                            "   -l <xxx.xxx.xxx.xxx> - logging ip\n");
                    exit(0);
                    break;
                }
                case 'b':
                {
                    i++;
                    if (argc > i) {
                        Xmsg::printf("Broadcast: %s = 0x%x\n", argv[i], inet_addr(argv[i]));
                        broadcastAddress = inet_addr(argv[i]);
                    }
                    break;
                }
                case 'l':
                {
                    i++;
                    if (argc > i) {
                        Xmsg::printf("Logout Adress: %s = 0x%x\n", argv[i], inet_addr(argv[i]));
                        logAddress = inet_addr(argv[i]);
                    }
                    break;
                }
                case 'd':
                {
                    i++;
                    if (argc > i) {
                        Xmsg::printf("TTY Device: %s\n", argv[i]);
                        delete [] ttyDevice;
                        ttyDevice = argv[i];
                    }
                    break;
                }
            }
        }
    }
    
    if(logAddress!=0xffffffff){
        oustream* udpLogBuffer = new oustream(logAddress,21216);
        cout.rdbuf(udpLogBuffer);
        //cerr.rdbuf(udpLogBuffer);
    }

    XshareMem* memt = new XshareMem();
    XUDPServ* dserv = new XUDPServ(21214);
    Xcom* xcomusb = new Xcom(ttyDevice, B9600);
    XbeeIf* xbeeintf = new XbeeIf(xcomusb);
    XUDPShareMem* udpsharemem = new XUDPShareMem(dserv, memt);
    XbeeContainer* contn = new XbeeContainer(memt, udpsharemem, xbeeintf);
    XUDPScaner* lis = new XUDPScaner(dserv, contn);
    XpackHandler* packHandler = new XpackHandler(contn, udpsharemem);
    Xpinger* pinger = new Xpinger(contn);

    //---detectors---
    packHandler->addDetector(new ADCXpackDetector(contn));
    packHandler->addDetector(new ButtonXpackDetector(contn));
    packHandler->addDetector(new PingXpackDetector(contn));
    //---------------
    
    dserv->setBroadcast(broadcastAddress);
    /*
         char ip[] = "192.168.1.102";
        long long_address = inet_addr (ip) ;
        char *dot_ip = inet_ntoa(long_address);
     */

    lis->startThread();
    dserv->setUDPListener((XUDPListener*) lis);
    dserv->startListenThread();
    xbeeintf->startScanThread();

    uint32_t buf = 0;

    contn->pingBroadcast();
    uint16_t pingCnt = 0;
    while (1) {
        Xpack* curpack = xbeeintf->read();
        if (curpack != NULL) {
            packHandler->procPack(curpack);
            //memt->printMem();
        }
        usleep(100000);
        if (pingCnt++ >= 50) {
            pinger->ping();
            Xmsg::printf("THE PING!!!\n");
            pingCnt = 0;
        }
    }
    return 0;
}